package com.astrofizzbizz.raspberrypicamera.client;

import java.util.ArrayList;

import com.astrofizzbizz.raspberrypicamera.shared.RaspberryPiException;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTMLTable;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.ListBox;

public class CameraSettingsPanel extends VerticalPanel
{
	RaspberryPiCamera entryPoint;
	ArrayList<CameraIntegerSetting> cameraSettingList = new ArrayList<CameraIntegerSetting>();
	ArrayList<CameraListSetting> cameraListSettingList = new ArrayList<CameraListSetting>();
	
	private String[] exposureModes = {"off", "auto", "night", "nightpreview", "backlight", "spotlight", "sports", "snow",
			"beach", "verylong", "fixedfps", "antishake", "fireworks"};
	private String[] awbModes = {"off", "auto", "sun", "cloud", "shade", "tungsten", "fluorescent", "incandescent", "flash", "horizon"};
	private String[] imageEffects = {"none", "negative", "solarise", "sketch", "denoise", "emboss", "oilpaint", "hatch", "gpen", 
			"pastel", "watercolour", "film", "blur", "saturation"};
	private String[] meteringModes = {"average", "spot", "backlit", "matrix"};
	
	public CameraSettingsPanel(RaspberryPiCamera entryPoint)
	{
		super();
		this.entryPoint = entryPoint;
		
		Grid grid = new Grid(16, 6);

		HTMLTable.CellFormatter formatter = grid.getCellFormatter();
		formatter.setHorizontalAlignment(0, 1, HasHorizontalAlignment.ALIGN_CENTER);
		formatter.setVerticalAlignment(0, 1, HasVerticalAlignment.ALIGN_MIDDLE);		
		
		grid.setWidget(0, 0, new Label("Setting"));
		grid.setWidget(0, 1, new Label("Value"));
		grid.setWidget(0, 3, new Label("Range"));
		grid.setWidget(0, 5, new Label("Enabled"));
		
		cameraSettingList.add(new CameraIntegerSetting("Width", 2592, 100, 2592, false, "-w", grid, 1));
		cameraSettingList.add(new CameraIntegerSetting("Height", 1944, 100, 1944, false, "-h", grid, 2));
		cameraSettingList.add(new CameraIntegerSetting("Quality", 100, 0, 100, false, "-q", grid, 3));
		cameraSettingList.add(new CameraIntegerSetting("Sharpness", 0, -100, 100, false, "-sh", grid, 4));
		cameraSettingList.add(new CameraIntegerSetting("Contrast", 0, -100, 100, false, "-co", grid, 5));
		cameraSettingList.add(new CameraIntegerSetting("Brightness", 50, 0, 100, false, "-br", grid, 6));
		cameraSettingList.add(new CameraIntegerSetting("Saturation", 0, -100, 100, false, "-sa", grid, 7));
		cameraSettingList.add(new CameraIntegerSetting("ISO", 100, 100, 800, false, "-ISO", grid, 8));
		cameraSettingList.add(new CameraIntegerSetting("EV Comp", 0, -10, 10, false, "-ev", grid, 9));
		cameraSettingList.add(new CameraIntegerSetting("Shutter Speed", 100, 1, 1000000, false, "-ss", grid, 10));
		cameraSettingList.add(new CameraIntegerSetting("Rotation", 0, 0, 359, false, "-rot", grid, 11));
		
		cameraListSettingList.add(new CameraListSetting("Exp. mode", exposureModes, false, "-ex", grid, 12));
		cameraListSettingList.add(new CameraListSetting("AWB. mode", awbModes, false, "-awb", grid, 13));
		cameraListSettingList.add(new CameraListSetting("Image Effects", imageEffects, false, "-ifx", grid, 14));
		cameraListSettingList.add(new CameraListSetting("Meter modes", meteringModes, false, "-mm", grid, 15));
		add(grid);
	}
	public String getSwitchSettings() throws RaspberryPiException
	{
		String switchSettings = "";
		if (cameraSettingList.size() > 0)
		{
			for (int ii = 0; ii < cameraSettingList.size(); ++ii)
			{
				switchSettings = switchSettings + cameraSettingList.get(ii).getSwitchCommand();
			}
		}
		if (cameraListSettingList.size() > 0)
		{
			for (int ii = 0; ii < cameraListSettingList.size(); ++ii)
			{
				switchSettings = switchSettings + cameraListSettingList.get(ii).getSwitchCommand();
			}
		}
		entryPoint.getStatusTextArea().addStatus("raspistill switch settings: " + switchSettings);
		return switchSettings; 
	}
	protected class CameraIntegerSetting
	{
		private String deviceName;
		private int lowerRange;
		private int upperRange;
		private CheckBox enabledCheckBox = new CheckBox();
		private TextBox settingTextBox = new TextBox();
		private String switchCommand;
		
		protected CameraIntegerSetting(String deviceName, int setting, int lowerRange, int upperRange, boolean enabled, String switchCommand, Grid grid, int gridRow)
		{
			settingTextBox.setSize("7.0em", "1.0em");
			this.deviceName = deviceName;
			this.lowerRange = lowerRange;
			this.upperRange = upperRange;
			enabledCheckBox.setValue(enabled);
			this.switchCommand = switchCommand;
			settingTextBox.setText(Integer.toString(setting));
			grid.setWidget(gridRow, 0, new Label(deviceName));
			grid.setWidget(gridRow, 1, settingTextBox);
			grid.setWidget(gridRow, 2, new Label(Integer.toString(lowerRange)));
			grid.setWidget(gridRow, 3, new Label("to"));
			grid.setWidget(gridRow, 4, new Label(Integer.toString(upperRange)));
			grid.setWidget(gridRow, 5, enabledCheckBox);
			
			HTMLTable.CellFormatter formatter = grid.getCellFormatter();
			formatter.setHorizontalAlignment(gridRow, 1, HasHorizontalAlignment.ALIGN_CENTER);
			formatter.setVerticalAlignment(gridRow, 1, HasVerticalAlignment.ALIGN_MIDDLE);		
			formatter.setHorizontalAlignment(gridRow, 2, HasHorizontalAlignment.ALIGN_LEFT);
			formatter.setVerticalAlignment(gridRow, 2, HasVerticalAlignment.ALIGN_MIDDLE);		
			formatter.setHorizontalAlignment(gridRow, 3, HasHorizontalAlignment.ALIGN_CENTER);
			formatter.setVerticalAlignment(gridRow, 3, HasVerticalAlignment.ALIGN_MIDDLE);		
			formatter.setHorizontalAlignment(gridRow, 4, HasHorizontalAlignment.ALIGN_RIGHT);
			formatter.setVerticalAlignment(gridRow, 4, HasVerticalAlignment.ALIGN_MIDDLE);		
			formatter.setHorizontalAlignment(gridRow, 5, HasHorizontalAlignment.ALIGN_CENTER);
			formatter.setVerticalAlignment(gridRow, 5, HasVerticalAlignment.ALIGN_MIDDLE);
			
			settingTextBox.addClickHandler(new EnableSettingClickHandler());

		}
		protected void checkRange() throws RaspberryPiException
		{
			int setting;
			String settingString = settingTextBox.getText().replaceAll("\\s+","");
			try {setting = Integer.parseInt(settingString);}
			catch (Exception e) 
			{
				entryPoint.getStatusTextArea().addStatus("ERROR: Bad setting value for " + deviceName);
				enabledCheckBox.setValue(false);
				throw new RaspberryPiException(e);
			}
			if (setting < lowerRange) setting = lowerRange;
			if (setting > upperRange) setting = upperRange;
			settingTextBox.setText(Integer.toString(setting));
		}
		protected String getSwitchCommand() throws RaspberryPiException
		{
			if (!enabledCheckBox.getValue()) return "";
			checkRange();
			String command = " " + switchCommand + " " + settingTextBox.getText();
			return command;
		}
		protected class EnableSettingClickHandler  implements ClickHandler
		{
			@Override
			public void onClick(ClickEvent event) {enabledCheckBox.setValue(true);}
			
		}
		
	}
	protected class CameraListSetting
	{
		private ListBox choiceListBox = new ListBox();
		private CheckBox enabledCheckBox = new CheckBox();
		private String switchCommand;
		
		protected CameraListSetting(String deviceName, String[] choices, boolean enabled, String switchCommand, Grid grid, int gridRow)
		{
			enabledCheckBox.setValue(enabled);
			this.switchCommand = switchCommand;
			choiceListBox.setVisibleItemCount(1);
			choiceListBox.setSize("8.0em", "2.0em");
			for (int ii = 0; ii < choices.length; ++ii) {choiceListBox.addItem(choices[ii]);}

			grid.setWidget(gridRow, 0, new Label(deviceName));
			grid.setWidget(gridRow, 1, choiceListBox);
			grid.setWidget(gridRow, 5, enabledCheckBox);

			HTMLTable.CellFormatter formatter = grid.getCellFormatter();
			formatter.setHorizontalAlignment(gridRow, 1, HasHorizontalAlignment.ALIGN_CENTER);
			formatter.setVerticalAlignment(gridRow, 1, HasVerticalAlignment.ALIGN_MIDDLE);		
			formatter.setHorizontalAlignment(gridRow, 2, HasHorizontalAlignment.ALIGN_LEFT);
			formatter.setVerticalAlignment(gridRow, 2, HasVerticalAlignment.ALIGN_MIDDLE);		
			formatter.setHorizontalAlignment(gridRow, 3, HasHorizontalAlignment.ALIGN_CENTER);
			formatter.setVerticalAlignment(gridRow, 3, HasVerticalAlignment.ALIGN_MIDDLE);		
			formatter.setHorizontalAlignment(gridRow, 4, HasHorizontalAlignment.ALIGN_RIGHT);
			formatter.setVerticalAlignment(gridRow, 4, HasVerticalAlignment.ALIGN_MIDDLE);		
			formatter.setHorizontalAlignment(gridRow, 5, HasHorizontalAlignment.ALIGN_CENTER);
			formatter.setVerticalAlignment(gridRow, 5, HasVerticalAlignment.ALIGN_MIDDLE);
			
			choiceListBox.addClickHandler(new EnableListClickHandler());
		}
		protected String getSwitchCommand() throws RaspberryPiException
		{
			if (!enabledCheckBox.getValue()) return "";
			String command = " " + switchCommand + " " + choiceListBox.getItemText(choiceListBox.getSelectedIndex());
			return command;
		}
		protected class EnableListClickHandler  implements ClickHandler
		{
			@Override
			public void onClick(ClickEvent event) {enabledCheckBox.setValue(true);}
			
		}
		
	}
}
